#ifndef BOARD_H
#define BOARD_H

#include <list>
#include <vector>
using namespace std;

#include "MoveableObj.h"

#define INIT_DROP_POS -400
#define INIT_DROP_POS_FROM_TOP -800
#define INIT_DROP_AFTER_ATE -200
#define TIME_TO_DROP_A_ROW 0.2f
#define TIME_DELAY_FOR_SOME_UPDATE 2	//second
#define TIME_DELAY_FOR_CHECK_EATABLE_IN_BOARD 0.3f

#define NUM_MISSION_ITEM_IN_MISSION_1 3
#define NUM_MISSION_ITEM_IN_MISSION_2 5
#define NUM_MISSION_ITEM_IN_MISSION_3 7
#define NUM_MISSION 3
#define W_SPRITE_DIAMOND 32
#define H_SPRITE_DIAMOND 32
#define X_MISSION 10
#define Y_MISSION 40

#define NUM_TYPE_DIAMOND_DEFAULT 7

class Texture;
class Cell;
class Diamond;
class AnimationSprite;
class Level;

enum BOARD_STATE
{
	BS_NONE,
	BS_INIT_DIAMOND,
	BS_READY,
	BS_MOVING_DIAMOND,
	BS_EATING,
};

class EatBlockDiamond
{
public:
	list<Diamond*> ateList;
	int effect;
	Diamond* mainDiamond;				//diamond touched when it was being ate

	//Property of diamond need replace
	Diamond* diamondBornWhenEatBlockExplode;
	int effectOfDiamondBornWhenEatBlockExplode;

	EatBlockDiamond();
	
	void AddDiamond(Diamond* diamond);
	void Pop();
	int Size();
	bool IsAllInState(int state);
	bool IsExistDiamond(Diamond* diamond);

	//Kill diamond when all diamond is in IDLE state, make it explode
	void KillDiamonds();
	~EatBlockDiamond();

	/*void SetEffect(int effect);
	void SetMainDiamond(Diamond* mainDiamond);*/
	void SetDiamondBornWhenEatBlockExplode(Diamond* diamond);
	void SetEffectOfDiamondBornWhenEatBlockExplode(int effect);

	int GetEffect(){return effect;}
	Diamond* GetMainDiamond(){return mainDiamond;}
	Diamond* GetDiamondBornWhenEatBlockExplode(){return diamondBornWhenEatBlockExplode;}
	int GetEffectOfDiamondBornWhenEatBlockExplode(){return effectOfDiamondBornWhenEatBlockExplode;}
};

#define FLASH_TIME 0.7f
#define SHOW_TIME 0.1f
class MissionItem
{
private:
	AnimationSprite* aniSprite;
	bool isFlashing;
	bool isShow;
	bool isActive;

	float flashDelay;
	float showDelay;
public:
	int id;

	MissionItem(int id);
	~MissionItem();
	
	void Update();
	void Render(int x, int y);

	void SetIsActive(bool isActive);

	bool GetIsActive();
};

class Board: public MoveableObj
{
private:
	Cell** cells;
	
	list<EatBlockDiamond*> eatBlockList;
	Texture* background;

	vector<MissionItem*> missionItems;

	int width;
	int height;

	int cellWidth;
	int cellHeight;

	int numTypeDiamond;

	//for effect drop when init level
	float dropRowDelay;
	int rowDrop;

	Cell* activeCell;			//cell be actived when touch it

	Vector* touchDownPos;
	Vector* touchUpPos;

	//timer
	float updateSomethingDelay;
	float checkEatableInBoardDelay;

	void RandomDiamond();
	void RandomDiamondWhenEat();
	void RandomDiamondId();
	bool CheckEatable(int x, int y);
	int CheckEatableAndSet(Cell* cell1, Cell* cell2);
	int CheckEatableFreeDiamond();
	void CheckEatableForDiamondInBoard();
	bool IsAllDiamondInState(int state);
	int NumDiamondInState(int state);
	void SwapDiamond(Cell* cell1, Cell* cell2);
	void DestroyDiamondInDieState();				// return num diamond are destroyed
	void SetDiamondMoveAfterEat();
	void RemoveDiamondFromFreeDiamondList();
	void DropInDiamondInitState();
	bool IsExistAndRemoveDiamondInFreeDiamondList(Diamond* diamond);
	void UpdateFreeDiamonds();
	void ProcessSpecialDiamondAte();
	void RandomMissionItems(int numItem);
	bool IsExistDiamondInAteBlockList(Diamond* diamond);

	//Check if diamond id match one diamond in mission item vector. Return mission completed or not
	bool CheckMissionMatch(int id);

	// Check win/lose state, if win : return 1, lose : return -1, nothing : return 0.
	bool CheckWin();

	bool CheckEatableIntArray(int x, int y, int* boa);
	int GetValue(int x, int y, int* boa);
	

public:
	list<Diamond*> freeDiamonds;				// diamonds have not put into cell yet
	Vector *posBackground;

	Board();
	Board(int x, int y, int cellWidth, int cellHeight);

	void Update();
	void Render();

	void TouchUp(int x, int y);
	void TouchDown(int x, int y);
	void TouchMove(int x, int y);

	int GetWidth(){return width;}
	int GetHeight(){return height;}

	void LoadMap(Level* level);
	void Reset();
	void SetState(int state);
	int CheckEatableAndSet(Cell* cell);

	int GetCellWidth(){return cellWidth;}
	int GetCellHeight(){return cellHeight;}
	Cell* GetCell(int x, int y);

	void SetBackground(Texture* texture);
	bool IsNoWay(int* outX, int* outY);
	void Hint();

	~Board();
};

#endif